Skip to content

Protect hosted anonymous tunnels with ownership tokens#18

Closed
mmkal wants to merge 4 commits into
mmkal/26/05/23/hosted-rate-limitsfrom
mmkal/26/05/24/hosted-ownership-tokens
Closed

Protect hosted anonymous tunnels with ownership tokens#18
mmkal wants to merge 4 commits into
mmkal/26/05/23/hosted-rate-limitsfrom
mmkal/26/05/24/hosted-ownership-tokens

Conversation

@mmkal
Copy link
Copy Markdown
Contributor

@mmkal mmkal commented May 23, 2026

Summary

Adds active-session ownership tokens for anonymous hosted captun.sh tunnels.

Behavior:

  • hosted anonymous connects require a captun-owner-token query param or x-captun-owner-token header
  • the first active connection for a tunnel name claims that token
  • reconnecting with the same token can replace its own active connection
  • connecting with a different token gets 409 Conflict without evicting the active tunnel
  • self-hosted/folder-routing and secret-protected deployments keep existing behavior
  • createCaptunTunnel returns ownerToken and accepts ownerToken for intentional same-owner replacement
  • the browser helper exposes the same ownerToken shape

Follow-up left out intentionally

Ownership is active-session only. Once the tunnel disconnects, the name is free for another anonymous token to claim. Persistent reservations, paid/custom names, active tunnel caps, byte/response caps, and edge throttles remain later hosted-safety work.

Verification

  • pnpm test -- test/worker.test.ts --testNamePattern 'ownership token|anonymous ownership|send an anonymous|reuse a returned'
  • pnpm run check
  • pnpm test
  • pnpm run build
  • CAPTUN_PUBLIC_E2E=1 pnpm vitest run test/public-hosted.test.ts

Note

Medium Risk
Introduces new ownership-token enforcement on the hosted connect path, changing connection/eviction semantics and adding new 400/409 failure modes for captun.sh clients. While scoped to anonymous hosted mode (skipped for self-hosted and secret-protected setups), mistakes could block legitimate reconnects or allow unintended tunnel takeovers.

Overview
Hosted captun.sh tunnels now require an anonymous ownership token on connect to prevent a second anonymous client from evicting an active tunnel by reusing the same subdomain.

The client API (createCaptunTunnel) now generates/propagates a token (query param by default, header override supported), returns it as tunnel.ownerToken, and allows reusing it via an ownerToken option; the hosted browser demo module was updated to match.

On the Worker side, CaptunServerShard now tracks { fetcher, ownerToken } per tunnel name: same-token reconnects replace the active session, different-token connects are rejected with 409, and missing/invalid tokens return 400 only for anonymous hosted (CUSTOM_HOSTNAME=captun.sh without CAPTUN_SECRET). Tests were expanded to cover these cases and to assert self-hosted “last connection wins” remains unchanged.

Reviewed by Cursor Bugbot for commit 0937d55. Bugbot is set up for automated code reviews on this repo. Configure here.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 23, 2026

Open in StackBlitz

npm i https://pkg.pr.new/captun@18

commit: 0937d55

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fd12c6a. Configure here.

Comment thread src/index.ts Outdated
@mmkal
Copy link
Copy Markdown
Contributor Author

mmkal commented May 24, 2026

Superseded by #20, which now combines the hosted rate-limit, ownership-token, conflict-message, and admission-module changes in one review.

@mmkal mmkal closed this May 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant